﻿using System;
using System.Web;
using System.Web.Mvc;
using CoreLibrary;
using CoreLibrary.Service;
using NLog;
using Web.Models.Common;
using Web.Models.Security;

namespace Web.Areas.Private.Controllers {

    public class AbstractPrivateController : Controller {

        [NonAction]
        protected T Locate<T> () where T : class, IService {
            return Services.Locate<T>();
        }

        [NonAction]
        protected T Locate<T> (string name) where T : class, IService {
            return Services.Locate<T>(name);
        }

        [NonAction]
        protected JsonResult Run<T> (IHasPassport model, Func<UserToken, T> func) {
            return Run(model.Passport, token => JSONResponse.CreateResponse(func(token)));
        }

        [NonAction]
        protected JsonResult Run(IHasPassport passport, Func<UserToken, JSONResponse> func) {
            return Run(passport.Passport, func);
        }

        [NonAction]
        private static JsonResult Run(string passport, Func<UserToken, JsonResult> func) {
            try {
                Asserts.NotBlank(passport, "Passport is required");
                var token = PassportUtil.ReadPassport(passport);
                if (!token.Enable) {
                    return JSONResponse.CreateUnauthenticated("account is not activated.");
                }

                return func(token);
            } 
            catch (Exception exception) {
                LogManager.GetCurrentClassLogger().ErrorException(exception.Message, exception);
                if (exception is ArgumentException) {
                    return JSONResponse.CreateInvalidRequest(exception.Message);
                }

                return JSONResponse.CreateInternalError(exception.Message);
            }
        }

        [NonAction]
        protected internal JsonResult Upload(string passport, Func<UserToken, JsonResult> func) {
            try {
                Asserts.NotBlank(passport, "Passport is required");
                var token = PassportUtil.ReadPassport(passport);
                if (!token.Enable) {
                    return JSONResponse.CreateUnauthenticated("Only Admin can perform file uploads");
                }
                return func(token);
            } 
            catch (Exception exception) {
                LogManager.GetCurrentClassLogger().ErrorException(string.Format("Downalod File Fail - {0}", exception.Message), exception);
                throw new HttpException(404, "File Not Found.");
            }
        }

        [NonAction]
        protected internal FileResult Download(string passport, Func<UserToken, FileResult> func) {
            try {
                Asserts.NotBlank(passport, "Passport is required");
                var token = PassportUtil.ReadPassport(passport);
                if (!token.Enable) {
                    throw new HttpException(404, "File Not Found.");
                }
                return func(token);
            } 
            catch (Exception exception) {
                LogManager.GetCurrentClassLogger().ErrorException(string.Format("Downalod File Fail - {0}", exception.Message), exception);
                throw new HttpException(404, "File Not Found.");
            }
        }
    }
}
